package com.todo.strategy.online.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.api.client.util.Lists;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.component.redis.RedisService;
import com.todo.strategy.common.constant.StrategyOnlineKeyBuild;
import com.todo.strategy.common.enums.StrategyRelationTypeEnum;
import com.todo.strategy.online.infrastructure.entity.po.WantRelationPO;
import com.todo.strategy.online.infrastructure.repository.WantRelationRepository;
import com.todo.strategy.online.application.convert.WantSetConvert;
import com.todo.strategy.online.application.entity.bo.WantRelationBO;
import com.todo.strategy.online.application.entity.context.RelationSimpleContext;
import com.todo.strategy.online.application.handler.relation.StrategyRelationFactory;
import com.todo.strategy.online.application.handler.relation.StrategyRelationStrategy;
import com.todo.strategy.online.application.service.WantRelationService;
import com.todo.strategy.online.application.service.WantSetService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * (WantRelation)表服务实现类
 *
 * @author zhangwenxiang
 * @since 2024-03-04 00:19:50
 */
@Slf4j
@Service("wantRelationService")
public class WantRelationServiceImpl implements WantRelationService {

    @Resource
    private WantRelationRepository wantRelationRepository;
    @Resource
    private WantSetService wantSetService;
    @Resource
    private StrategyRelationFactory strategyRelationFactory;
    @Resource
    private RedisService redisService;

    @Override
    public Boolean insertWantRelation(WantRelationBO wantRelationBO) {
        if (wantRelationBO == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        if (wantRelationBO.getRelationType() != null && !StrategyRelationTypeEnum.CUSTOM.equals(wantRelationBO.getRelationType())) {
            if (wantRelationBO.getRelationId() == null || wantRelationBO.getRelationId() < 0) {
                throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "关联信息出错，关联失败");
            }
        }
        //过滤已经存在的数据，同时计算数据总数【注：当前自定义数据初期不做过滤】
        List<WantRelationBO> wantRelationBOList = queryWantRelationBySetId(wantRelationBO.getWantId());
        WantRelationBO sameWantRelationBO = wantRelationBOList.stream()
                .filter(item -> Objects.nonNull(item.getRelationId()))
                .filter(item -> item.getRelationId().equals(wantRelationBO.getRelationId()))
                .findFirst().orElse(null);
        if (sameWantRelationBO != null) {
            log.info("WantRelationService#insertWantRelation 新增我想去关联信息,当前数据已经存在，默认成功 wantRelationBO：【{}】", JSONObject.toJSONString(wantRelationBO));
            return true;
        }

        //非自定义类型枚举，则通过查询填充对应数据
        if (!StrategyRelationTypeEnum.CUSTOM.equals(wantRelationBO.getRelationType())) {
            StrategyRelationStrategy strategy = strategyRelationFactory.getStrategy(wantRelationBO.getRelationType());
            if (strategy == null) {
                log.error("WantRelationService#insertWantRelation 新增我想去关联信息失败，数据关联类型错误，无当前数据处理器 无法操作 wantRelationBO：【{}】", JSONObject.toJSONString(wantRelationBO));
                throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "关联信息出错，请检查后操作");
            }
            RelationSimpleContext context = strategy.relationSimpleHandel(wantRelationBO.getRelationId());
            if (context == null) {
                log.error("WantRelationService#insertWantRelation 新增我想去关联信息失败，数据关联类型查询为空 默认保存空数据 wantRelationBO：【{}】", JSONObject.toJSONString(wantRelationBO));
            } else {
                WantRelationBO.CustomInfo customInfo = new WantRelationBO.CustomInfo();
                customInfo.setName(context.getName());
                customInfo.setAddress(context.getAddress());
                customInfo.setLon(context.getLon());
                customInfo.setLat(context.getLat());
                customInfo.setRemark(context.getRemark());
                customInfo.setCustomType(context.getRelationType().getCode());
                wantRelationBO.setCustomInfo(customInfo);
            }
        }

        WantRelationPO wantRelationPO = WantSetConvert.convertToWantRelationPO(wantRelationBO);
        Boolean insertResult = wantRelationRepository.insertWantRelationPO(wantRelationPO);
        if (insertResult) {
            wantSetService.updateWantSetRelationCount(wantRelationPO.getWantId(), wantRelationBOList.size() + 1);
            String wantRelationKey = StrategyOnlineKeyBuild.wantRelationKey(wantRelationPO.getWantId());
            redisService.hSet(wantRelationKey, String.valueOf(wantRelationBO.getId()), JSONObject.toJSONString(wantRelationBO));
        }
        return insertResult;
    }

    @Override
    public Boolean removeWantRelationByIdList(Long wantId, List<Long> idList) {
        if (wantId == null || wantId < 0 || CollectionUtils.isEmpty(idList)) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        List<WantRelationBO> wantRelationBOS = queryWantRelationBySetId(wantId);
        if (CollectionUtils.isEmpty(wantRelationBOS)) {
            return true;
        }
        Boolean updated = wantRelationRepository.removeWantRelationByIdList(wantId, idList);
        if (updated) {
            int count = wantRelationBOS.size() - idList.size();
            wantSetService.updateWantSetRelationCount(wantId, Math.max(count, 0));
            String wantRelationKey = StrategyOnlineKeyBuild.wantRelationKey(wantId);
            idList.forEach(item -> redisService.hDel(wantRelationKey, String.valueOf(item)));
        }
        return updated;
    }

    @Override
    public List<WantRelationBO> queryWantRelationBySetId(Long wantId) {
        if (wantId == null || wantId < 0) {
            return Lists.newArrayList();
        }
        String relationKey = StrategyOnlineKeyBuild.wantRelationKey(wantId);
        Map<String, String> cacheMap = redisService.hGetAll(relationKey);
        if (MapUtils.isNotEmpty(cacheMap)) {
            return cacheMap.values().stream()
                    .map(item -> JSONObject.parseObject(item, WantRelationBO.class))
                    .collect(Collectors.toList());
        }

        List<WantRelationPO> wantRelationPOList = wantRelationRepository.queryWantRelationPOByContentId(wantId);
        if (CollectionUtils.isEmpty(wantRelationPOList)) {
            log.info("WantRelationService#queryWantRelationBySetId 根据我想去Id查询数据完成，数据为空 wantId：【{}】", wantId);
            return Lists.newArrayList();
        }
        List<WantRelationBO> collect = wantRelationPOList.stream().map(WantSetConvert::convertToWantRelationBO).collect(Collectors.toList());
        for (WantRelationBO item : collect) {
            redisService.hSet(relationKey, String.valueOf(item.getId()), JSONObject.toJSONString(item));
        }
        return collect;
    }

    @Override
    public Boolean removeWantRelationByWantId(Long wantId) {
        if (wantId == null || wantId < 0) {
            return false;
        }
        Boolean result = wantRelationRepository.removeWantRelationPOById(wantId);
        if (result) {
            String wantRelationKey = StrategyOnlineKeyBuild.wantRelationKey(wantId);
            redisService.del(wantRelationKey);
        }
        return result;
    }
}
